home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / Tools / Misc / bgui / Examples / Source / MultiColumn.c < prev    next >
C/C++ Source or Header  |  2000-05-09  |  36KB  |  820 lines

  1. /*
  2.  * @(#) $Header: /cvsroot/bgui/examples/MultiColumn.c,v 41.11 2000/05/09 20:33:46 mlemos Exp $
  3.  *
  4.  * MultiColumn.c
  5.  *
  6.  * (C) Copyright 1998 Manuel Lemos.
  7.  * (C) Copyright 1995 Jaba Development.
  8.  * (C) Copyright 1995 Jan van den Baard.
  9.  * All Rights Reserved.
  10.  *
  11.  * $Log: MultiColumn.c,v $
  12.  * Revision 41.11  2000/05/09 20:33:46  mlemos
  13.  * Bumped to revision 41.11
  14.  *
  15.  * Revision 1.2  2000/05/09 19:59:02  mlemos
  16.  * Merged with the branch Manuel_Lemos_fixes.
  17.  *
  18.  * Revision 1.1.2.3  1999/02/19 05:03:56  mlemos
  19.  * Added support to build with Storm C.
  20.  *
  21.  * Revision 1.1.2.2  1998/04/27 00:13:01  mlemos
  22.  * Ensured that the stack is never less than 8000 bytes.
  23.  *
  24.  * Revision 1.1.2.1  1998/02/28 17:45:30  mlemos
  25.  * Ian sources
  26.  *
  27.  *
  28.  */
  29.  
  30. /*
  31. dcc MultiColumn.c -proto -mi -ms -mRR -lbgui
  32. quit
  33. */
  34.  
  35. long __stack=8000;
  36.  
  37. #include "DemoCode.h"
  38.  
  39. #include <dos/exall.h>
  40. #include <utility/hooks.h>
  41.  
  42. #include <clib/macros.h>
  43.  
  44. #include <string.h>
  45. #include <stdio.h>
  46.  
  47. /*
  48. **      This is the data were going to add
  49. **      to the listview object. It is a simple
  50. **      structure in which the file-information
  51. **      is stored. This data is created in the
  52. **      LISTV_Resource hook from a pointer
  53. **      to a ExAllData structure.
  54. **/
  55. typedef struct {
  56.         UBYTE                   fi_FileName[ 108 ];
  57.         UBYTE                   fi_Size[ 11 ];
  58.         UBYTE                   fi_Date[ 32 ];
  59.         BOOL                    fi_IsDir;
  60. } FILEINFO;
  61.  
  62. /*
  63. **      The LISTV_Resource hook is used to create
  64. **      the FILEINFO structures from a struct ExAllData
  65. **      at create time. At delete time the FILEINFO
  66. **      structure is simply deallocated.
  67. **/
  68. SAVEDS ASM APTR ResourceHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvResource *lvr )
  69. {
  70.         struct ExAllData        *ead;
  71.         FILEINFO                *fi;
  72.         struct DateTime          dt;
  73.         APTR                     return_code = NULL;
  74.  
  75.         /*
  76.         **      What must we do?
  77.         **/
  78.         switch ( lvr->lvr_Command ) {
  79.  
  80.                 case    LVRC_MAKE:
  81.                         /*
  82.                         **      Create a FILEINFO structure.
  83.                         **      BGUI has passed us a pointer to a
  84.                         **      ExAllData structure. Here we
  85.                         **      convert it to a FILEINFO structure
  86.                         **      which, eventually, get's added to
  87.                         **      the listview.
  88.                         **/
  89.                         if ( fi = ( FILEINFO * )AllocVec( sizeof( FILEINFO ), MEMF_PUBLIC )) {
  90.                                 /*
  91.                                 **      Pick up the ExAllData.
  92.                                 **/
  93.                                 ead = ( struct ExAllData * )lvr->lvr_Entry;
  94.                                 /*
  95.                                 **      Copy the name.
  96.                                 **/
  97.                                 strcpy( &fi->fi_FileName[ 0 ], ead->ed_Name );
  98.                                 /*
  99.                                 **      Format the size text. We can do all sorts of
  100.                                 **      fancy stuff here like using the locale.library
  101.                                 **      formatting stuff but hey, it's just a demo ;)
  102.                                 **/
  103.                                 if ( ead->ed_Type < 0 ) {
  104.                                         fi->fi_IsDir = FALSE;
  105.                                         sprintf( &fi->fi_Size[ 0 ], "%ld", ead->ed_Size );
  106.                                 } else {
  107.                                         fi->fi_IsDir = TRUE;
  108.                                         strcpy( &fi->fi_Size[ 0 ], "(dir)" );
  109.                                 }
  110.                                 /*
  111.                                 **      Convert the date to a string.
  112.                                 **/
  113.                                 dt.dat_Stamp    = *(( struct DateStamp * )&ead->ed_Days );
  114.                                 dt.dat_Format   = FORMAT_CDN;
  115.                                 dt.dat_Flags    = DTF_SUBST | DTF_FUTURE;
  116.                                 dt.dat_StrDay   = NULL;
  117.                                 dt.dat_StrDate  = &fi->fi_Date[ 0 ];
  118.                                 dt.dat_StrTime  = NULL;
  119.                                 /*
  120.                                 **      Format date.
  121.                                 **/
  122.                                 DateToStr( &dt );
  123.                                 /*
  124.                                 **      Return a pointer to the created
  125.                                 **      FILEINFO structure.
  126.                                 **/
  127.                                 return_code = ( APTR )fi;
  128.                         }
  129.                         break;
  130.  
  131.                 case    LVRC_KILL:
  132.                         /*
  133.                         **      Simply deallocate the FILEINFO
  134.                         **      structure which has been created with
  135.                         **      LVRC_MAKE above.
  136.                         **/
  137.                         FreeVec( lvr->lvr_Entry );
  138.                         break;
  139.         }
  140.         /*
  141.         **      Pointer to FILEINFO or NULL.
  142.         **/
  143.         return( return_code );
  144. }
  145.  
  146. /*
  147. **      The listview will have three columns.
  148. **
  149. **      Name            Size            Date
  150. **
  151. **      The following globals will contain the maximum
  152. **      width of each of these columns.
  153. **/
  154. UWORD   MaxName, MaxSize, MaxDate;
  155.  
  156. /*
  157. **      This global stores the total width of the
  158. **      listview drawing area.
  159. **/
  160. UWORD   TotalWidth = 0;
  161.  
  162. /*
  163. **      This boolean determines wether the hook must
  164. **      re-compute the column sizes.
  165. **/
  166. BOOL    ReCompCols = TRUE;
  167.  
  168. /*
  169. **      We use 16 pixels as a minimum inner-column spacing.
  170. **/
  171. #define INNER_SPACE                     16
  172.  
  173. /*
  174. **      This routine re-computes the minimum column
  175. **      sizes when necessary.
  176. **/
  177. VOID ReComputeColumns( struct RastPort *rp, Object *obj, UWORD list_width )
  178. {
  179.         FILEINFO                        *fi;
  180.         UWORD                            tmp, total;
  181.  
  182.         /*
  183.         **      A re-computation is necessary when:
  184.         **
  185.         **      1) The ReCompCols flag is TRUE.
  186.         **      2) The with of the listview has changed.
  187.         **/
  188.         if ( ReCompCols || ( TotalWidth != list_width )) {
  189.                 /*
  190.                 **      Our listview also has a title entry.
  191.                 **      Here we compute the default column
  192.                 **      sizes accoording to this title.
  193.                 **/
  194.                 MaxName = TextLength( rp, "Name:", 6 ) + INNER_SPACE;
  195.                 MaxSize = TextLength( rp, "Size:", 6 ) + INNER_SPACE;
  196.                 MaxDate = TextLength( rp, "Date:", 6 );
  197.                 /*
  198.                 **      Now we loop through the entries to find
  199.                 **      out the largest width of the three columns.
  200.                 **/
  201.                 if ( fi = ( FILEINFO * )FirstEntry( obj )) {
  202.                         /*
  203.                         **      Loop until all are done.
  204.                         **/
  205.                         while ( fi ) {
  206.                                 /*
  207.                                 **      Compute width of the Name: column
  208.                                 **      for this entry.
  209.                                 **/
  210.                                 tmp = TextLength( rp, &fi->fi_FileName[ 0 ], strlen( &fi->fi_FileName[ 0 ] )) + INNER_SPACE;
  211.                                 /*
  212.                                 **      Is it bigger than the last one?
  213.                                 **      If so store it.
  214.                                 **/
  215.                                 if ( tmp > MaxName ) MaxName = tmp;
  216.                                 /*
  217.                                 **      Compute width of the Size: column
  218.                                 **      for this entry.
  219.                                 **/
  220.                                 tmp = TextLength( rp, &fi->fi_Size[ 0 ], strlen( &fi->fi_Size[ 0 ] )) + INNER_SPACE;
  221.                                 /*
  222.                                 **      Is it bigger than the last one?
  223.                                 **      If so store it.
  224.                                 **/
  225.                                 if ( tmp > MaxSize ) MaxSize = tmp;
  226.                                 /*
  227.                                 **      Compute width of the Date: column
  228.                                 **      for this entry.
  229.                                 **/
  230.                                 tmp = TextLength( rp, &fi->fi_Date[ 0 ], strlen( &fi->fi_Date[ 0 ] ));
  231.                                 /*
  232.                                 **      Is it bigger than the last one?
  233.                                 **      If so store it.
  234.                                 **/
  235.                                 if ( tmp > MaxDate ) MaxDate = tmp;
  236.                                 /*
  237.                                 **      Pick up the next entry.
  238.                                 **/
  239.                                 fi = ( FILEINFO * )NextEntry( obj, fi );
  240.                         }
  241.                 }
  242.                 /*
  243.                 **      Compute the total columns width.
  244.                 **/
  245.                 total = MaxName + MaxSize + MaxDate;
  246.                 /*
  247.                 **      If there's room left over we
  248.                 **      distribute it between the columns so
  249.                 **      we get a nice even spacing between
  250.                 **      them.
  251.                 **/
  252.                 if ( list_width > total ) {
  253.                         MaxName += ( list_width - total ) >> 1;
  254.                         MaxSize += ( list_width - total ) >> 1;
  255.                 }
  256.                 /*
  257.                 **      All done. Set the re-compute flag to
  258.                 **      FALSE and store the list width.
  259.                 **/
  260.                 ReCompCols = FALSE;
  261.                 TotalWidth = list_width;
  262.         }
  263. }
  264.  
  265. /*
  266. **      The default DrawInfo pens. Just in case we don't
  267. **      get them from the system.
  268. **/
  269. UWORD   DefDriPens[] = {
  270.         0, 1, 1, 2, 1, 3, 1, 0, 2, 1, 2, 1 };
  271.  
  272. /*
  273. **      Listview rendering hook. Here's where the magic starts ;)
  274. **/
  275. SAVEDS ASM UBYTE *DisplayHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvRender *lvr )
  276. {
  277.         struct TextExtent               te;
  278.         UBYTE                          *str;
  279.         FILEINFO                       *fi = ( FILEINFO * )lvr->lvr_Entry;
  280.         UWORD                          *pens, numc, w, l, cw, h;
  281.  
  282.         /*
  283.         **      Pick up the DrawInfo pen array.
  284.         **/
  285.         pens = lvr->lvr_DrawInfo ? lvr->lvr_DrawInfo->dri_Pens : DefDriPens;
  286.         /*
  287.         **      Pick up the width of the list.
  288.         **/
  289.         w = lvr->lvr_Bounds.MaxX - lvr->lvr_Bounds.MinX + 1;
  290.         /*
  291.         **      Pick up the list left-edge;
  292.         **/
  293.         l = lvr->lvr_Bounds.MinX;
  294.         /*
  295.         **      Pick up the height of the entry.
  296.         **/
  297.         h = lvr->lvr_Bounds.MaxY - lvr->lvr_Bounds.MinY + 1;
  298.  
  299.         /*
  300.         **      First we render the background.
  301.         **/
  302.         SetAPen( lvr->lvr_RPort, lvr->lvr_State == LVRS_SELECTED ? pens[ FILLPEN ] : pens[ BACKGROUNDPEN ] );
  303.         SetDrMd( lvr->lvr_RPort, JAM1 );
  304.  
  305.         RectFill( lvr->lvr_RPort, lvr->lvr_Bounds.MinX,
  306.                                   lvr->lvr_Bounds.MinY,
  307.                                   lvr->lvr_Bounds.MaxX,
  308.                                   lvr->lvr_Bounds.MaxY );
  309.  
  310.         /*
  311.         **      When we are passed a NULL entry pointer
  312.         **      we are presumed to render the title. If your
  313.         **      listview does not have a title simply
  314.         **      recompute the columns and return NULL.
  315.         **      We have a title so here we go.
  316.         **/
  317.         if ( ! fi ) {
  318.                 /*
  319.                 **      Recompute the column sizes. The routine
  320.                 **      itself will decide if it's necessary.
  321.                 **/
  322.                 ReComputeColumns( lvr->lvr_RPort, obj, w );
  323.                 /*
  324.                 **      Set the pen for the title-entry.
  325.                 **/
  326.                 SetAPen( lvr->lvr_RPort, pens[ FILLPEN ] );
  327.         } else {
  328.                 /*
  329.                 **      Set the pen for a non-title entry. Ofcourse
  330.                 **      we can (should?) differenciate between normal and
  331.                 **      selected here but I wont ;)
  332.                 **/
  333.                 if ( fi->fi_IsDir ) SetAPen( lvr->lvr_RPort, pens[ HIGHLIGHTTEXTPEN ] );
  334.                 else                SetAPen( lvr->lvr_RPort, pens[ TEXTPEN ] );
  335.         }
  336.         /*
  337.         **      Obtain Name: column width. We check it against the
  338.         **      total list width so we do not go outside the
  339.         **      given area.
  340.         **/
  341.         cw = MIN( MaxName, w );
  342.  
  343.         /*
  344.         **      Pick up the name string or, when this
  345.         **      is a title call, the string "Name:".
  346.         **/
  347.         str = fi ? &fi->fi_FileName[ 0 ] : ( UBYTE * )"Name:";
  348.  
  349.         /*
  350.         **      Compute the number of character we
  351.         **      can render.
  352.         **/
  353.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  354.  
  355.         /*
  356.         **      If the number of characters is
  357.         **      0 we can stop right here and now.
  358.         **/
  359.         if ( ! numc ) return( NULL );
  360.  
  361.         /*
  362.         **      Move to the correct position
  363.         **      and render the text.
  364.         **/
  365.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  366.         Text( lvr->lvr_RPort, str, numc );
  367.  
  368.         /*
  369.         **      Adjust the left-edge and width to
  370.         **      get past the Name: column.
  371.         **/
  372.         l += cw;
  373.         w  = MAX(( WORD )( w - cw ), 0 );
  374.  
  375.         /*
  376.         **      Obtain Size: column width. We check it against the
  377.         **      total list width so we do not go outside the
  378.         **      given area.
  379.         **/
  380.         cw = MIN( MaxSize, w );
  381.  
  382.         /*
  383.         **      Pick up the size string or, when this
  384.         **      is a title call, the string "Size:".
  385.         **/
  386.         str = fi ? &fi->fi_Size[ 0 ] : ( UBYTE * )"Size:";
  387.  
  388.         /*
  389.         **      Compute the number of character we
  390.         **      can render.
  391.         **/
  392.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  393.  
  394.         /*
  395.         **      If the number of characters is
  396.         **      0 we can stop right here and now.
  397.         **/
  398.         if ( ! numc ) return( NULL );
  399.  
  400.         /*
  401.         **      Move to the correct position
  402.         **      and render the text.
  403.         **/
  404.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  405.         Text( lvr->lvr_RPort, str, numc );
  406.  
  407.         /*
  408.         **      Adjust the left-edge and width to
  409.         **      get past the Size: column.
  410.         **/
  411.         l += cw;
  412.         w  = MAX(( WORD )( w - cw ), 0 );
  413.  
  414.         /*
  415.         **      Obtain Date column width. We check it against the
  416.         **      total list width so we do not go outside the
  417.         **      given area.
  418.         **/
  419.         cw = MIN( MaxDate, w );
  420.  
  421.         /*
  422.         **      Pick up the date string or, when this
  423.         **      is a title call, the string "Date:".
  424.         **/
  425.         str = fi ? &fi->fi_Date[ 0 ] : ( UBYTE * )"Date:";
  426.  
  427.         /*
  428.         **      Compute the number of character we
  429.         **      can render.
  430.         **/
  431.         numc = TextFit( lvr->lvr_RPort, str, strlen( str ), &te, NULL, 0, cw, h );
  432.  
  433.         /*
  434.         **      If the number of characters is
  435.         **      0 we can stop right here and now.
  436.         **/
  437.         if ( ! numc ) return( NULL );
  438.  
  439.         /*
  440.         **      Move to the correct position
  441.         **      and render the text.
  442.         **/
  443.         Move( lvr->lvr_RPort, l, lvr->lvr_Bounds.MinY + lvr->lvr_RPort->TxBaseline );
  444.         Text( lvr->lvr_RPort, str, numc );
  445.  
  446.         /*
  447.         **      Return NULL. This is important. If we return a non-NULL
  448.         **      value the listview class will think it is a pointer to
  449.         **      the text to render and try to render it.
  450.         **/
  451.         return( NULL );
  452. }
  453.  
  454. /*
  455. **      The comparrison hook. We do a simple name, dir/file
  456. **      comparrison here.
  457. **/
  458. SAVEDS ASM LONG CompareHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct lvCompare *lvc )
  459. {
  460.         FILEINFO                *a = ( FILEINFO * )lvc->lvc_EntryA;
  461.         FILEINFO                *b = ( FILEINFO * )lvc->lvc_EntryB;
  462.  
  463.         /*
  464.         **      First we do a type comparrison to get the
  465.         **      directories at the top of the list.
  466.         **/
  467.         if ( a->fi_IsDir && ! b->fi_IsDir      ) return( -1L );
  468.         else if ( ! a->fi_IsDir && b->fi_IsDir ) return( 1L );
  469.  
  470.         /*
  471.         **      Otherwise we do a simple, case insensitive,
  472.         **      name string comparrison.
  473.         **/
  474.         return( stricmp( &a->fi_FileName[ 0 ], &b->fi_FileName[ 0 ] ));
  475. }
  476.  
  477. /*
  478. **      A IDCMP hook for the window which allows us
  479. **      to control the listview from the keyboard.
  480. **/
  481. SAVEDS ASM VOID ScrollHookFunc( REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct IntuiMessage *msg )
  482. {
  483.         struct Window                   *window;
  484.         Object                          *lv_obj = ( Object * )hook->h_Data;
  485.  
  486.         /*
  487.         **      Obtain window pointer.
  488.         **/
  489.         GetAttr( WINDOW_Window,        obj,    ( ULONG * )&window );
  490.  
  491.         /*
  492.         **      What key is pressed?
  493.         **/
  494.         switch ( msg->Code ) {
  495.  
  496.                 case    0x4C:
  497.                         /*
  498.                         **      UP              - Move entry up.
  499.                         **      SHIFT + UP      - Move page up.
  500.                         **      CTRL + UP       - Move to the top.
  501.                         **/
  502.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  503.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Up, TAG_END );
  504.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  505.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_First, TAG_END );
  506.                         else
  507.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Previous, TAG_END );
  508.                         break;
  509.  
  510.                 case    0x4D:
  511.                         /*
  512.                         **      DOWN            - Move entry down.
  513.                         **      SHIFT + DOWN    - Move page down.
  514.                         **      CTRL + DOWN     - Move to the end.
  515.                         **/
  516.                         if ( msg->Qualifier & ( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ))
  517.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Page_Down, TAG_END );
  518.                         else if ( msg->Qualifier & IEQUALIFIER_CONTROL )
  519.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Last, TAG_END );
  520.                         else
  521.                                 SetGadgetAttrs(( struct Gadget * )lv_obj, window, NULL, LISTV_Select, LISTV_Select_Next, TAG_END );
  522.  
  523.                         break;
  524.  
  525.                 case    0x43:
  526.                 case    0x44:
  527.                         /*
  528.                         **      RETURN or ENTER - Report the listview ID to the event handler.
  529.                         **/
  530.                         DoMethod( obj, WM_REPORT_ID, (( struct Gadget * )lv_obj )->GadgetID, 0L );
  531.                         break;
  532.         }
  533. }
  534.  
  535. /*
  536. **      The hook structures as added to the
  537. **      listview object and window object.
  538. **
  539. **      If your compiler complaints about the
  540. **      HOOKFUNC typedef uncomment the below line.
  541. **/
  542.  
  543. /* typedef ULONG (*HOOKFUNC)(); */
  544.  
  545. struct Hook ResourceHook = { NULL, NULL, (HOOKFUNC)ResourceHookFunc, NULL, NULL };
  546. struct Hook DisplayHook  = { NULL, NULL, (HOOKFUNC)DisplayHookFunc,  NULL, NULL };
  547. struct Hook CompareHook  = { NULL, NULL, (HOOKFUNC)CompareHookFunc,  NULL, NULL };
  548. struct Hook ScrollHook   = { NULL, NULL, (HOOKFUNC)ScrollHookFunc,   NULL, NULL };
  549.  
  550. /*
  551. **      Scan the directory "name".
  552. **/
  553. VOID ScanDirectory( UBYTE *name, Object *obj )
  554. {
  555.         struct ExAllControl             *eac;
  556.         struct ExAllData                *ead, *tmp;
  557.         struct FileInfoBlock            *fib;
  558.         BPTR                             lock;
  559.         BOOL                             ismore;
  560.  
  561.         /*
  562.         **      We need to recompute the columns.
  563.         **/
  564.         ReCompCols = TRUE;
  565.  
  566.         /*
  567.         **      Get a lock to the directory.
  568.         **/
  569.         if ( lock = Lock( name, ACCESS_READ )) {
  570.                 /*
  571.                 **      Allocate a FileInfoBlock structure.
  572.                 **/
  573.                 if ( fib = ( struct FileInfoBlock * )AllocDosObject( DOS_FIB, NULL )) {
  574.                         /*
  575.                         **      Examine the lock.
  576.                         **/
  577.                         if ( Examine( lock, fib )) {
  578.                                 /*
  579.                                 **      Is this a directory?
  580.                                 **/
  581.                                 if ( fib->fib_DirEntryType > 0 ) {
  582.                                         /*
  583.                                         **      Allocate ExAll() control structure.
  584.                                         **/
  585.                                         if ( eac = ( struct ExAllControl * )AllocDosObject( DOS_EXALLCONTROL, NULL )) {
  586.                                                 /*
  587.                                                 **      Set key to NULL.
  588.                                                 **/
  589.                                                 eac->eac_LastKey = NULL;
  590.                                                 /*
  591.                                                 **      Allocate ExAll() buffer.
  592.                                                 **/
  593.                                                 if ( ead = ( struct ExAllData * )AllocVec( 10 * sizeof( struct ExAllData ), MEMF_PUBLIC )) {
  594.                                                         /*
  595.                                                         **      Read directory.
  596.                                                         **/
  597.                                                         do {
  598.                                                                 /*
  599.                                                                 **      Fill buffer.
  600.                                                                 **/
  601.                                                                 ismore = ExAll( lock, ead, 10 * sizeof( struct ExAllData ), ED_DATE, eac );
  602.  
  603.                                                                 /*
  604.                                                                 **      Errors? Done?
  605.                                                                 **/
  606.                                                                 if (( ! ismore ) && ( IoErr() != ERROR_NO_MORE_ENTRIES ))
  607.                                                                         break;
  608.  
  609.                                                                 /*
  610.                                                                 **      Entries read?
  611.                                                                 **/
  612.                                                                 if ( ! eac->eac_Entries )
  613.                                                                         continue;
  614.  
  615.                                                                 /*
  616.                                                                 **      Pick up data pointer.
  617.                                                                 **/
  618.                                                                 tmp = ead;
  619.  
  620.                                                                 /*
  621.                                                                 **      Add the entries.
  622.                                                                 **/
  623.                                                                 do {
  624.                                                                         AddEntry( NULL, obj, tmp, LVAP_SORTED );
  625.                                                                         /*
  626.                                                                         **      Next...
  627.                                                                         **/
  628.                                                                         tmp = tmp->ed_Next;
  629.                                                                 } while ( tmp );
  630.                                                         } while ( ismore );
  631.                                                         /*
  632.                                                         **      Deallocate ExAll() buffer.
  633.                                                         **/
  634.                                                         FreeVec( ead );
  635.                                                 }
  636.                                                 /*
  637.                                                 **      Deallocate ExAll() control structure.
  638.                                                 **/
  639.                                                 FreeDosObject( DOS_EXALLCONTROL, eac );
  640.                                         }
  641.                                 }
  642.                         }
  643.                         /*
  644.                         **      Deallocate FileInfoBlock structure.
  645.                         **/
  646.                         FreeDosObject( DOS_FIB, fib );
  647.                 }
  648.                 /*
  649.                 **      Release lock.
  650.                 **/
  651.                 UnLock( lock );
  652.         }
  653. }
  654.  
  655. /*
  656. **      And were off...
  657. **/
  658. #define ID_QUIT                 1
  659. #define ID_LIST                 2
  660. #define ID_NEWDIR               3
  661.  
  662. VOID StartDemo( void )
  663. {
  664.         struct RDArgs                   *ra;
  665.         struct Window                   *win;
  666.         Object                          *WO_DirWin, *GO_DirList, *GO_Quit, *GO_NewDir;
  667.         FILEINFO                        *fi;
  668.         LONG                             dname = 0L;
  669.         ULONG                            signal, rc;
  670.         UBYTE                            name[ 512 ], *ptr;
  671.         BOOL                             running = TRUE;
  672.  
  673.         /*
  674.         **      Parse command line?
  675.         **/
  676.         if ( ra = ReadArgs( "NAME", &dname, NULL )) {
  677.                 /*
  678.                 **      Copy the name into the buffer.
  679.                 **/
  680.                 if ( dname ) strcpy( name, ( UBYTE * )dname );
  681.                 else         name[ 0 ] = 0;
  682.                 /*
  683.                 **      Create the listview object.
  684.                 **/
  685.                 GO_DirList = ListviewObject,
  686.                         LISTV_ResourceHook,             &ResourceHook,
  687.                         LISTV_DisplayHook,              &DisplayHook,
  688.                         LISTV_TitleHook,                &DisplayHook,
  689.                         LISTV_CompareHook,              &CompareHook,
  690.                         GA_ID,                          ID_LIST,
  691.                 EndObject;
  692.                 /*
  693.                 **      Put it in the IDCMP hook.
  694.                 **/
  695.                 ScrollHook.h_Data = ( APTR )GO_DirList;
  696.                 /*
  697.                 **      Create the window.
  698.                 **/
  699.                 WO_DirWin = WindowObject,
  700.                         WINDOW_Title,           "MultiCol",
  701.                         WINDOW_RMBTrap,         TRUE,
  702.                         WINDOW_ScaleWidth,      50,
  703.                         WINDOW_ScaleHeight,     30,
  704.                         WINDOW_AutoAspect,      TRUE,
  705.                         WINDOW_SmartRefresh,    TRUE,
  706.                         WINDOW_IDCMPHookBits,   IDCMP_RAWKEY,
  707.                         WINDOW_IDCMPHook,       &ScrollHook,
  708.                         WINDOW_MasterGroup,
  709.                                 VGroupObject, HOffset( 4 ), VOffset( 4 ), Spacing( 4 ), GROUP_BackFill, SHINE_RASTER,
  710.                                         StartMember,
  711.                                                 VGroupObject,
  712.                                                         StartMember, GO_DirList, EndMember,
  713.                                                         StartMember,
  714.                                                                 GO_NewDir = KeyString( NULL, name, 512, ID_NEWDIR ), FixMinHeight,
  715.                                                         EndMember,
  716.                                                 EndObject,
  717.                                         EndMember,
  718.                                         StartMember,
  719.                                                 HGroupObject,
  720.                                                         VarSpace( DEFAULT_WEIGHT ),
  721.                                                         StartMember, GO_Quit = KeyButton( "_Quit", ID_QUIT ), EndMember,
  722.                                                         VarSpace( DEFAULT_WEIGHT ),
  723.                                                 EndObject, FixMinHeight,
  724.                                         EndMember,
  725.                                 EndObject,
  726.                 EndObject;
  727.  
  728.                 /*
  729.                 **      Window created OK?
  730.                 **/
  731.                 if ( WO_DirWin ) {
  732.                         /*
  733.                         **      Add gadget key.
  734.                         **/
  735.                         if ( GadgetKey( WO_DirWin, GO_Quit, "q" )) {
  736.                                 /*
  737.                                 **      Open the window.
  738.                                 **/
  739.                                 if ( win = WindowOpen( WO_DirWin )) {
  740.                                         /*
  741.                                         **      Obtain signal mask.
  742.                                         **/
  743.                                         GetAttr( WINDOW_SigMask, WO_DirWin, &signal );
  744.                                         /*
  745.                                         **      Read in the directory.
  746.                                         **/
  747.                                         WindowBusy( WO_DirWin );
  748.                                         ScanDirectory( name, GO_DirList );
  749.                                         WindowReady( WO_DirWin );
  750.                                         /*
  751.                                         **      Refresh the list.
  752.                                         **/
  753.                                         RefreshList( win, GO_DirList );
  754.                                         /*
  755.                                         **      Poll messages...
  756.                                         **/
  757.                                         do {
  758.                                                 Wait( signal );
  759.                                                 while (( rc = HandleEvent( WO_DirWin )) != WMHI_NOMORE ) {
  760.                                                         switch ( rc ) {
  761.  
  762.                                                                 case    ID_QUIT:
  763.                                                                 case    WMHI_CLOSEWINDOW:
  764.                                                                         running = FALSE;
  765.                                                                         break;
  766.  
  767.                                                                 case    ID_LIST:
  768.                                                                         /*
  769.                                                                         **      Get selected entry.
  770.                                                                         **/
  771.                                                                         if ( fi = ( FILEINFO * )FirstSelected( GO_DirList )) {
  772.                                                                                 /*
  773.                                                                                 **      Is the entry a directory?
  774.                                                                                 **/
  775.                                                                                 if ( fi->fi_IsDir ) {
  776.                                                                                         /*
  777.                                                                                         **      AddPart() the name to the buffer.
  778.                                                                                         **/
  779.                                                                                         AddPart( name, &fi->fi_FileName[ 0 ], 512 );
  780.                                                                                         /*
  781.                                                                                         **      Refresh the string gadget.
  782.                                                                                         **/
  783.                                                                                         SetGadgetAttrs(( struct Gadget * )GO_NewDir, win, NULL, STRINGA_TextVal, name, TAG_END );
  784.                                                                                         /*
  785.                                                                                         **      Re-read the list.
  786.                                                                                         **/
  787.                                                                                         refreshDir:
  788.                                                                                         WindowBusy( WO_DirWin );
  789.                                                                                         ClearList( win, GO_DirList );
  790.                                                                                         ScanDirectory( name, GO_DirList );
  791.                                                                                         RefreshList( win, GO_DirList );
  792.                                                                                         WindowReady( WO_DirWin );
  793.                                                                                 }
  794.                                                                         }
  795.                                                                         break;
  796.  
  797.                                                                 case    ID_NEWDIR:
  798.                                                                         /*
  799.                                                                         **      Copy the new name to the buffer.
  800.                                                                         **/
  801.                                                                         GetAttr( STRINGA_TextVal, GO_NewDir, ( ULONG * )&ptr );
  802.                                                                         strcpy( name, ptr );
  803.                                                                         goto refreshDir;
  804.                                                         }
  805.                                                 }
  806.                                         } while ( running );
  807.                                 }
  808.                         }
  809.                         /*
  810.                         **      Kill the object.
  811.                         **/
  812.                         DisposeObject( WO_DirWin );
  813.                 }
  814.                 /*
  815.                 **      Delete the ReadArgs structure.
  816.                 **/
  817.                 FreeArgs( ra );
  818.         }
  819. }
  820.